﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using NetJavap.ConstantInfos;

namespace NetJavap
{
    public class MethodInfo : ClassMember, IWithAttributeMember, IWithMethodDescriptorMember
    {
        private AccessFlags _accessFlags;
        private UInt16 _nameIndex;
        private UInt16 _descriptorIndex;
        private UInt16 _attributesCount;
        private AttributeInfo[] _attributes;

        private ConstantUtf8Info _name;
        private ConstantUtf8Info _descriptor;
        private String _fullName;
        private TypeInfo[] _parameters;
        private TypeInfo _returnType;

        public AccessFlags AccessFlags { get { return this._accessFlags; } }
        public ConstantUtf8Info Name
        {
            get
            {
                if (this._name == null)
                {
                    this._name = this.ParentClass.ConstantPool[this._nameIndex] as ConstantUtf8Info;
                }
                return this._name;
            }
        }
        public ConstantUtf8Info Descriptor
        {
            get
            {
                if (this._descriptor == null)
                {
                    this._descriptor = this.ParentClass.ConstantPool[this._descriptorIndex] as ConstantUtf8Info;
                }
                return this._descriptor;
            }
        }
        public AttributeInfo[] Attributes
        {
            get
            {
                return this._attributes;
            }
        }
        public TypeInfo ReturnType
        {
            get
            {
                if (this._returnType == null)
                {
                    this.Init();
                }
                return this._returnType;
            }
        }
        public TypeInfo[] Parameters
        {
            get
            {
                if (this._parameters == null)
                {
                    this.Init();
                }
                return this._parameters;
            }
        }
        public String FullName
        {
            get
            {
                if (this._fullName == null)
                {
                    this._fullName = this.ParentClass.FullName + "." + this.Name + ":" + this.Descriptor;
                }
                return this._fullName;
            }
        }

        public void Init()
        {
            ArrayBuilder.AnalyseDescriptor(this.Descriptor.Value, out this._parameters, out this._returnType);
        }

        public MethodInfo(BinaryReader reader, JavaClass cls)
            : base(cls)
        {
            this._accessFlags = (AccessFlags)reader.ReadUInt16BE();
            this._nameIndex = reader.ReadUInt16BE();
            this._descriptorIndex = reader.ReadUInt16BE();
            this._attributesCount = reader.ReadUInt16BE();
            this._attributes = ArrayBuilder.BuildAttributes(reader, cls, this._attributesCount, this);
        }

        public override string ToString()
        {
            return this.FullName;
        }
    }

}
